﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SudokuHelper.Model.Values {
    public abstract class ValueRelationDispatcher {
        #region Dispatch methods


        /// <summary>
        /// Dispatches two unknown relations. First stage of dispatching
        /// </summary>
        /// <param name="unknown1">First relation</param>
        /// <param name="unknown2">Second relation</param>
        public void Dispatch(IValueRelation unknown1, IValueRelation unknown2) {
            unknown1.Dispatch(unknown2, this);
        }

        /// <summary>
        /// Dispatches unknown entity <paramref name="unknown"/> with known <paramref name="userValue"/>. Second stage of dispatching
        /// </summary>
        /// <param name="userValue">User value</param>
        /// <param name="unknown">Unknown value</param>
        public void Dispatch(UserValue userValue, IValueRelation unknown) {
            unknown.Dispatch(userValue, this);
        }

        /// <summary>
        /// Dispatches unknown entity <paramref name="unknown"/> with known <paramref name="calculatedValue"/>. Second stage of dispatching
        /// </summary>
        /// <param name="calculatedValue"></param>
        /// <param name="unknown"></param>
        public void Dispatch(CalculatedValue calculatedValue, IValueRelation unknown) {
            unknown.Dispatch(calculatedValue, this);
        }

        /// <summary>
        /// Dispatches unknown entity <paramref name="unknown"/> with known <paramref name="valueRange"/>. Second stage of dispatching
        /// </summary>
        /// <param name="valueRange"></param>
        /// <param name="unknown"></param>
        public void Dispatch(ValueRange valueRange, IValueRelation unknown) {
            unknown.Dispatch(valueRange, this);
        }

        #endregion

        #region Performance methods

        /// <summary>
        /// Performs an actual operation between two instances of UserValue
        /// </summary>
        /// <param name="userValue1"></param>
        /// <param name="userValue2"></param>
        public abstract void Perform(UserValue userValue1, UserValue userValue2);

        /// <summary>
        /// Performs an actual operation between <paramref name="userValue"/> and <paramref name="calculatedValue"/>
        /// </summary>
        /// <param name="userValue">User value</param>
        /// <param name="calculatedValue">Calculated value</param>
        public abstract void Perform(UserValue userValue, CalculatedValue calculatedValue);

        /// <summary>
        /// Performs an actual operation between <paramref name="userValue"/> and <paramref name="valueRange"/>
        /// </summary>
        /// <param name="userValue">User value</param>
        /// <param name="valueRange">Value range</param>
        public abstract void Perform(UserValue userValue, ValueRange valueRange);

        /// <summary>
        /// Performs an actual operation between two calculated values
        /// </summary>
        /// <param name="calculatedValue1">First value</param>
        /// <param name="calculatedValue2">Second value</param>
        public abstract void Perform(CalculatedValue calculatedValue1, CalculatedValue calculatedValue2);

        /// <summary>
        /// Performs an actual operation between <paramref name="calculatedValue"/> and <paramref name="valueRange"/>
        /// </summary>
        /// <param name="calculatedValue">Calculated value</param>
        /// <param name="valueRange">Value range</param>
        public abstract void Perform(CalculatedValue calculatedValue, ValueRange valueRange);

        /// <summary>
        /// Performs an actual operation between two ranges
        /// </summary>
        /// <param name="range1">First range</param>
        /// <param name="range2">Second range</param>
        public abstract void Perform(ValueRange range1, ValueRange range2);

        #endregion
    }
}
